package com.wdy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName: LurCache
 * @Description: TODO
 * @Date: 2019/12/31 17:46
 * @Author: wangdy001
 * @Version: 1.0
 */
public class LurCache {
    private final Logger LOG = LoggerFactory.getLogger(LurCache.class);
    private final Map<String, Node> map;

    class Node {
        private String username;
        private UserAccount userAccount;
        private Node previous;
        private Node next;

        public Node(String username, UserAccount userAccount) {
            this.username = username;
            this.userAccount = userAccount;
        }
    }

    Node head, end;
    int capacity;

    public LurCache(int capacity) {
        this.capacity = capacity;
        this.map = new ConcurrentHashMap<>(capacity);
    }

    public void setUserAccount(String username, UserAccount userAccount) {
        if(map.containsKey(username)) {
            LOG.error("{} is exits! update it and sethead", userAccount);
            Node old = map.get(username);
            remove(old);
            setHead(old);
        } else {
            if(capacity > map.size()) {
                LOG.error("reach max capacity, remove last node");
                map.remove(end.username);
                remove(end);
            }
            Node node = new Node(username, userAccount);
            map.put(username, node);
            setHead(node);
        }
    }

    public void remove(Node node){
        if(node.previous != null) {
            node.previous.next = node.next;
        } else {
            head = node.next;
        }

        if(node.next != null) {
            node.next.previous = node.previous;
        } else {
            end = node.previous;
        }
    }

    public void setHead(Node node) {
        node.next = head;
        node.previous = null;
        if(head != null) {
            head.previous = node;
        }
        head = node;
        if(end == null) {
            end = head;
        }
    }
}
